package com.yaodian100.ec.creditcard.service.impl;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.hibernate.Hibernate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import com.yaodian100.core.common.dao.ObjectDao;
import com.yaodian100.core.common.dao.impl.CommonCriteria;
import com.yaodian100.core.common.exception.CoreException;
import com.yaodian100.core.common.service.impl.DomainServiceImpl;
import com.yaodian100.core.common.utils.ServerValue;
import com.yaodian100.ec.creditcard.entity.Creditcard;
import com.yaodian100.ec.creditcard.entity.CreditcardDetail;
import com.yaodian100.ec.creditcard.entity.Creditcard.Range;
import com.yaodian100.ec.creditcard.service.CreditcardDetailService;
import com.yaodian100.ec.creditcard.service.CreditcardService;
import com.yaodian100.ec.product.entity.Product;
import com.yaodian100.ec.product.entity.ProductCategory;
import com.yaodian100.ec.product.service.ProductService;

public class CreditcardServiceImpl extends DomainServiceImpl<Creditcard> implements CreditcardService {

	private final Logger logger = LoggerFactory.getLogger(CreditcardServiceImpl.class);

	@Autowired
	private ProductService productService;

	@Autowired
	private CreditcardDetailService creditcardDetailService;

	private ObjectDao<CreditcardDetail> creditcardDetailDao;

	@Override
	public Creditcard getValidCreditcard(String productId, String cookie, String domain) {
		if (StringUtils.isBlank(cookie)) {
			cookie = "yaodian100";
		}

		if (StringUtils.isBlank(domain)) {
			domain = ServerValue.getFrontHostname().substring(7);
		}

		Product p = productService.get(productId);
		List<Long> campaignIds = new ArrayList<Long>();

		// 1. 依productId找符合且最新的信用卡活动
		StringBuilder sb = new StringBuilder();
		sb.append("SELECT ID FROM EC_CREDITCARD_CAMPAIGN ").append("WHERE IS_DELETE = 0 ") // 未删除
				.append("AND IS_ENABLE = 1 ") // 已启用
				.append("AND SYSDATE BETWEEN START_DATE AND END_DATE ").append("AND CAMPAIGN_RANGE = 2 ") // 活动类型为类别
				.append("AND DOMAIN = ? ") // domain
				.append("AND (COOKIE LIKE '%" + cookie + "%' OR COOKIE IS NULL) ").append(
						"AND CAMPAIGN_RANGN_DET LIKE '%" + productId + "%' ").append("ORDER BY MODIFY_DATE DESC ");

		List attrs = new ArrayList();
		attrs.add(domain);
		List ids = getDao().getSQLQueryByList(sb.toString(), attrs, 0, -1);

		if (ids.size() > 0) {
			campaignIds.add(new Long(ids.get(0).toString()));
		}

		// 2. 依product category找符合且最新的信用卡活动
		Iterator<ProductCategory> cats = p.getProductCategories().iterator();

		sb = new StringBuilder();
		sb.append("SELECT ID FROM EC_CREDITCARD_CAMPAIGN ").append("WHERE IS_DELETE = 0 ") // 未删除
				.append("AND IS_ENABLE = 1 ") // 已启用
				.append("AND SYSDATE BETWEEN START_DATE AND END_DATE ").append("AND CAMPAIGN_RANGE = 1 ") // 活动类型为类别
				.append("AND DOMAIN = ? ") // domain
				.append("AND (COOKIE LIKE '%" + cookie + "%' OR COOKIE IS NULL) ");
		if (cats.hasNext()) {
			sb.append("AND ( ");
			int i = 0;
			while (cats.hasNext()) {
				ProductCategory pc = cats.next();
				if (i == 0) {
					sb.append("CAMPAIGN_RANGN_DET LIKE '%" + pc.getCategoryId() + "%' ");
				} else {
					sb.append("OR CAMPAIGN_RANGN_DET LIKE '%" + pc.getCategoryId() + "%' ");
				}
				i++;
			}
			sb.append(") ");
		}
		sb.append("ORDER BY MODIFY_DATE DESC ");

		attrs = new ArrayList();
		attrs.add(domain);
		ids = getDao().getSQLQueryByList(sb.toString(), attrs, 0, -1);

		if (ids.size() > 0) {
			campaignIds.add(new Long(ids.get(0).toString()));
		}

		// 3.
		sb = new StringBuilder();
		sb.append("SELECT ID FROM EC_CREDITCARD_CAMPAIGN ").append("WHERE IS_DELETE = 0 ") // 未删除
				.append("AND IS_ENABLE = 1 ") // 已启用
				.append("AND SYSDATE BETWEEN START_DATE AND END_DATE ").append("AND CAMPAIGN_RANGE = 0 ") // 活动类型为类别
				.append("AND DOMAIN = ? ") // domain
				.append("AND (COOKIE LIKE '%" + cookie + "%' OR COOKIE IS NULL) ").append("ORDER BY MODIFY_DATE DESC ");

		attrs = new ArrayList();
		attrs.add(domain);
		ids = getDao().getSQLQueryByList(sb.toString(), attrs, 0, -1);

		if (ids.size() > 0) {
			campaignIds.add(new Long(ids.get(0).toString()));
		}

		if (campaignIds.size() == 0) {
			return null;
		}

		CommonCriteria cri = new CommonCriteria();
		cri.addIn("id", campaignIds);
		List<Creditcard> tar = super.getList(0, -1, cri, new String[] { "modifyDate desc" });

		return tar.get(0);
	}

	@Override
	public CreditcardDetail getValidCreditcard(String productId, String detailId, String period, String cookie,
			String domain) {
		logger.info("##### productId=" + productId);
		logger.info("##### detailId=" + detailId);
		logger.info("##### period=" + period);
		logger.info("##### cookie=" + cookie);
		logger.info("##### domain=" + domain);

		if (StringUtils.isBlank(cookie)) {
			cookie = "yaodian100";
		}

		Product p = productService.get(productId);
		CreditcardDetail cd = creditcardDetailService.get(new Long(detailId).longValue());
		Creditcard c = cd.getCreditcard();

		if (c.getRange().equals(Range.Product)) {
			if (c.getCampaignRangeDet().indexOf(productId) == -1) {
				logger.info("Creditcard Campaign(id=" + c.getId() + ", detailId=" + detailId + ") dose not has Product(id="
						+ productId + "). ");
				return null;
			}
		} else if (c.getRange().equals(Range.Category)) {
			String[] categoryIds = c.getCampaignRangeDet().split(",");
			boolean isCategoryExist = false;
			for (String cid : categoryIds) {
				for (ProductCategory pc : p.getProductCategories()) {
					if (pc.getCategoryId().toString().equals(cid)) {
						isCategoryExist = true;
						break;
					}
				}
			}
			if (!isCategoryExist) {
				logger.info("Creditcard Campaign(id=" + c.getId() + ", detailId=" + detailId + ") dose not has Product(id="
						+ productId + "). ");
				return null;
			}
		}

		if (!(StringUtils.isBlank(c.getCookie()) || c.getCookieArray().contains(cookie))) {
			logger.info("Creditcard Campaign(id=" + c.getId() + ", detailId=" + detailId + ") dose not has cookie(" + cookie
					+ "). ");
			return null;
		}

		if (!domain.equals(c.getDomain())) {
			logger.info("Creditcard Campaign(id=" + c.getId() + ", detailId=" + detailId + ") dose not has domain(" + domain
					+ "). ");
			return null;
		}

		Map<String, String> periodMap = cd.getPeriodMap();
		if (periodMap.get(period) == null) {
			logger.info("Creditcard Campaign(id=" + c.getId() + ", detailId=" + detailId + ") dose not has period(" + period
					+ "). ");
			return null;
		}

		// System.out.println("Exist");
		return cd;
	}

	@Override
	@Transactional(readOnly = false)
	public boolean saveCreditcardCombine(Creditcard main, List<CreditcardDetail> details) throws CoreException {
		try {
			main = getDao().save(main);
			for (CreditcardDetail detail : details) {
				detail.setCreditcard(main);
				detail = getCreditcardDetailDao().save(detail);
			}
		} catch (Exception e) {
			return false;
		}
		return true;
	}

	@Override
	@Transactional(readOnly = false)
	public boolean updateCreditcardCombine(Creditcard main, List<CreditcardDetail> details) throws CoreException {
		try {
			main = getDao().update(main);
			for (CreditcardDetail detail : details) {
				if (detail.getId() > 0) {
					detail = getCreditcardDetailDao().update(detail);
				} else {
					detail.setCreditcard(main);
					detail = getCreditcardDetailDao().save(detail);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	@Override
	public Creditcard get(Serializable oid) throws CoreException {
		Creditcard entity = super.get(oid);
		Hibernate.initialize(entity.getCardDetails());
		return entity;
	}

	@Override
	@Transactional(readOnly = false)
	public void delete(Creditcard entity) throws CoreException {
		entity.setDelete(true);
		getDao().update(entity);
	}

	@Override
	public List<Creditcard> getList(int firstResult, int maxResults, CommonCriteria criteria, String[] sortOrder)
			throws CoreException {
		if (criteria == null) {
			criteria = new CommonCriteria();
		}
		criteria.addEq("delete", false);
		List<Creditcard> campaignList = super.getList(firstResult, maxResults, criteria, sortOrder);
		for (Creditcard entity : campaignList) {
			Hibernate.initialize(entity.getCardDetails());
		}
		return campaignList;
	}

	@Override
	public Number getListSize(CommonCriteria criteria) throws CoreException {
		if (criteria == null) {
			criteria = new CommonCriteria();
		}
		criteria.addEq("delete", false);
		return super.getListSize(criteria);
	}

	@Override
	public List<Creditcard> getAll(int firstResult, int maxResults, String[] sortOrder) throws CoreException {
		CommonCriteria criteria = new CommonCriteria();
		criteria.addEq("delete", false);
		return getList(0, -1, criteria, sortOrder);
	}

	@Override
	public Number getAllSize() throws CoreException {
		CommonCriteria criteria = new CommonCriteria();
		criteria.addEq("delete", false);
		return getListSize(criteria);
	}

	// Getters & Setters
	public ProductService getProductService() {
		return productService;
	}

	public void setProductService(ProductService productService) {
		this.productService = productService;
	}

	public CreditcardDetailService getCreditcardDetailService() {
		return creditcardDetailService;
	}

	public void setCreditcardDetailService(CreditcardDetailService creditcardDetailService) {
		this.creditcardDetailService = creditcardDetailService;
	}

	public ObjectDao<CreditcardDetail> getCreditcardDetailDao() {
		return creditcardDetailDao;
	}

	public void setCreditcardDetailDao(ObjectDao<CreditcardDetail> creditcardDetailDao) {
		this.creditcardDetailDao = creditcardDetailDao;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.yaodian100.ec.creditcard.service.CreditcardService#chkAvailableCreditCardDetails(com.yaodian100.ec.creditcard
	 * .entity.Creditcard, java.math.BigDecimal)
	 */
	@Override
	public boolean chkAvailableCreditCardDetails(Creditcard creditcard, BigDecimal price) {
		List<String> ids = new ArrayList<String>();
		for (CreditcardDetail detail : creditcard.getCardDetails()) {
			for (String period : detail.getPeriodMap().keySet()) {
				if (price.floatValue() >= Float.valueOf(detail.getDownLimitMap().get(period))
						&& price.floatValue() <= Float.valueOf(detail.getUpLimitMap().get(period))) {
					ids.add(String.valueOf(detail.getId()));
				}
			}
		}
		if (null != ids && ids.size() > 0) {
			return true;
		} else {
			return false;
		}
	}
}
